package com.bobi.tfca.ui.mainnavigation.user

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModel
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.bobi.tfca.R
import com.bobi.tfca.base.BaseFragment
import com.bobi.tfca.constants.PageElementIdConstant
import com.bobi.tfca.databinding.FragmentUserBinding
import com.bobi.tfca.network.ApiResponse
import com.bobi.tfca.network.api.MemberAPI
import com.bobi.tfca.network.client.AppCache
import com.bobi.tfca.ui.app.MainActivity
import com.bobi.tfca.util.LogUtil
import com.bobi.tfca.util.RealPathUtil
import com.bumptech.glide.Glide
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File


class UserFragment : BaseFragment<FragmentUserBinding, ViewModel>(
    FragmentUserBinding::inflate,
    null,
    true
) {

    private lateinit var imagePickerLauncher: ActivityResultLauncher<Intent>
    private lateinit var imageView: ImageView
    private lateinit var llMemberInfo: LinearLayout
    private lateinit var tvLoginout: TextView
    private lateinit var ivHeadPhoto: ImageView

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private val REQUIRED_PERMISSIONS = arrayOf(
        Manifest.permission.READ_EXTERNAL_STORAGE
    )

    private val requestPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
            if (permissions.all { it.value }) {
                // 如果所请求的所有权限都被授予，则执行相应的操作，比如打开相册
            } else {
                // 如果有任何一个权限被拒绝，则可以向用户解释为什么需要这些权限，并提供一个再次请求的机会
                Toast.makeText(requireActivity(), "选择图片需要权限", Toast.LENGTH_SHORT).show()
            }
        }


    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun checkPermissions(): Boolean {
        val isAllGranted = REQUIRED_PERMISSIONS.all {
            ContextCompat.checkSelfPermission(
                requireContext(),
                it
            ) == PackageManager.PERMISSION_GRANTED
        }
        // 如果权限没有授予，请求权限
        if (!isAllGranted) {
            requestPermissionLauncher.launch(REQUIRED_PERMISSIONS)
            return false
        } else {
            return true
        }
    }

    // 在适当的时候调用请求权限的方法
    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun openPictureChooser() {
        if (checkPermissions()) {
            // 如果权限已被授予，则执行相应的操作，比如打开相册
            // 点击图片后，更改图片
            // 打开图片选择器
            val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
            imagePickerLauncher.launch(intent)
        }
    }


    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    override fun initFragment(
        binding: FragmentUserBinding,
        viewModel: ViewModel?,
        savedInstanceState: Bundle?
    ) {
        val loginStatus = AppCache.checkLoginStatus()

        // 设置菜单为监听的
        setMenuVisiblityListener(binding)

        llMemberInfo = binding.llMemberInfo
        tvLoginout = binding.tvLoginout
        ivHeadPhoto = binding.ivHeadPhoto

        // 设置个人头像，姓名，id，会龄，身份
        val myInfo = AppCache.getMyInfo()
        if (myInfo != null) {
            binding.tvUid.text = myInfo.memberId.toString()
            binding.tvRole.text = myInfo.role
            binding.userName.text = myInfo.memberName
            binding.tvMemberAge.text = myInfo.memberAge
            val url = myInfo.picture
            if (url.isNotBlank() && (!"null".equals(url))) {
                Glide.with(this).load(url).placeholder(R.mipmap.head)
                    .into(ivHeadPhoto)
            }
        }
        imageView = binding.ivHeadPhoto
        // 修改头像
        binding.ivHeadPhoto.setOnClickListener {
            // 需要登录或注册才能访问
            if (loginStatus) {
                uploadImage()
            } else {
                Toast.makeText(requireActivity(), "请登录或注册", Toast.LENGTH_SHORT).show()
            }
        }

        binding.llMyActivity.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.myActivityFragment)
        }

        binding.llMemberAudit.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.memberApplyFragment)
        }

        binding.llMemberManage.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.memberManageFragment)
        }

        binding.llUpdatePassword.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.changePasswordFragment)
        }

        binding.llForgetPassword.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.forgetPasswordFragment)
        }

        binding.llRegister.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.registerMemberFragment)
        }

        binding.llQuitAss.setOnClickListener {
            requireActivity().findNavController(R.id.app_nav).navigate(R.id.quitAssFragment)
        }


        if (loginStatus) {
            llMemberInfo.visibility = View.VISIBLE
            tvLoginout.text = "退出登录"
        } else {
            llMemberInfo.visibility = View.INVISIBLE
            tvLoginout.text = "登录"
        }

        binding.llLogout.setOnClickListener {
            // 如果是登录状态，则是退出
            // 是否登录，未登录则不跳转，并提示请登录或注册
            val loginStatus = AppCache.checkLoginStatus()
            if (loginStatus) {
                // 如果是登录状态，则是登出
                publicViewModel!!.apply {
                    request(MemberAPI::class.java).logout().getResponse {
                        it.collect {
                            when (it) {
                                is ApiResponse.Error -> {
                                    LogUtil.e(it.errMsg)
                                }

                                ApiResponse.Loading -> LogUtil.e("Loading")
                                is ApiResponse.Success -> {
                                    withContext(Dispatchers.Main) {
                                        Toast.makeText(
                                            requireActivity(),
                                            "登出成功！",
                                            Toast.LENGTH_SHORT
                                        ).show()
                                        // 设置会员信息为不可见和登录，可不设置，因为resumeFragment会自动设置
                                        // llMemberInfo.visibility = View.INVISIBLE
                                        // tvLoginout.text = "登录"

                                        // 清除SharedPreferences里的登录信息
                                        spUtil.clearLoginInfo()
                                        // 清除AppCache
                                        AppCache.setMyInfo(null)
                                        // 断开socket
                                        AppCache.logout()
                                        // 清除token
                                        publicViewModel!!.requestBuilder.authorization(null)
                                        // 重置菜单元素
                                        publicViewModel!!.resetVisiblePageElements()

                                        val intent = Intent(requireContext(), MainActivity::class.java)
                                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
                                        startActivity(intent)
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                requireActivity().findNavController(R.id.app_nav).navigate(R.id.loginFragment)
            }
        }

        // 注册图片选择器
        registerImagePickerResult()
    }

    private fun setMenuVisiblityListener(binding: FragmentUserBinding) {
        publicViewModel!!.apply {
            visiblePageElements.observe(this@UserFragment) {
                val elementVisibility1 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_MY_ACTIVITY)
                binding.llMyActivity.visibility = elementVisibility1
                binding.llMyActivityLine.visibility = elementVisibility1

                val elementVisibility2 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_MEMBER_AUDIT)
                binding.llMemberAudit.visibility = elementVisibility2
                binding.llMemberAuditLine.visibility = elementVisibility2

                val elementVisibility3 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_MEMBER_MANAGE)
                binding.llMemberManage.visibility = elementVisibility3
                binding.llMemberManageLine.visibility = elementVisibility3

                val elementVisibility4 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_UPDATE_PASSWORD)
                binding.llUpdatePassword.visibility = elementVisibility4
                binding.llUpdatePasswordLine.visibility = elementVisibility4

                val elementVisibility5 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_FORGET_PASSWORD)
                binding.llForgetPassword.visibility = elementVisibility5
                binding.llForgetPasswordLine.visibility = elementVisibility5

                val elementVisibility6 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_REGISTER)
                binding.llRegister.visibility = elementVisibility6
                binding.llRegisterLine.visibility = elementVisibility6

                val elementVisibility7 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_QUIT_ASS)
                binding.llQuitAss.visibility = elementVisibility7
                binding.llQuitAssLine.visibility = elementVisibility7

                val elementVisibility8 =
                    getElementVisibility(PageElementIdConstant.FRAGMENT_USER_LL_LOGOUT)
                binding.llLogout.visibility = elementVisibility8
            }
        }
    }

    override fun resumeFragment(viewModel: ViewModel?) {
        super.resumeFragment(viewModel)
        val loginStatus = AppCache.checkLoginStatus()
        if (loginStatus) {
            llMemberInfo.visibility = View.VISIBLE
            tvLoginout.text = "退出登录"
        } else {
            Glide.with(this).load(R.mipmap.head).into(ivHeadPhoto)
            llMemberInfo.visibility = View.INVISIBLE
            tvLoginout.text = "登录"
        }
        // 请求元素列表，以便设置可见性
        publicViewModel!!.getCurrentAllMenus()
    }

    private fun registerImagePickerResult() {
        imagePickerLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    val selectedImageUri: Uri? = result.data?.data
                    selectedImageUri?.let {
                        val file = getFileFromUri(selectedImageUri)
                        val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
                        val body =
                            MultipartBody.Part.createFormData("file", file!!.name, requestFile)
                        if (body != null) {
                            LogUtil.i("选择了图片")
                            // 将图片上传至服务器，由服务器上传至腾讯云，将返回的地址设为图片地址。
                            uploadImageToServer(
                                body
                            )
                        } else {
                            LogUtil.i("图片未选择")
                        }
                    }
                }
            }
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun uploadImage() {
        openPictureChooser()
    }

    private fun getFileFromUri(uri: Uri): File? {
        val filePath = RealPathUtil.getRealPath(requireActivity(), uri)
        return if (filePath != null) File(filePath) else null
    }


    /**
     * 将图片上传至服务器，由服务器上传至腾讯云，将返回的地址设为图片地址。
     */
    private fun uploadImageToServer(
        file: MultipartBody.Part
    ) {
        publicViewModel!!.apply {
            request(MemberAPI::class.java).updateMyHeadPhoto(file).getResponse {
                it.collect {
                    when (it) {
                        is ApiResponse.Error -> {
                            LogUtil.e(it.errMsg)
                        }

                        ApiResponse.Loading -> LogUtil.e("Loading")

                        is ApiResponse.Success -> {
                            withContext(Dispatchers.Main) {
                                LogUtil.i("上传成功")
                                val url = it.data!!.data ?: ""
                                if (url.isNotBlank() && (!"null".equals(url))) {
                                    // 更改AppCache里的个人信息头像
                                    AppCache.getMyInfo().picture = url
                                    if (this@UserFragment.isAdded() && !this@UserFragment.isDetached()) {
                                        Glide.with(this@UserFragment).load(url)
                                            .placeholder(R.mipmap.head)
                                            .into(imageView)
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}